package com.android.miniskirt.service;

import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.PrivacyListManager;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smackx.ChatStateManager;

import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;

import com.android.miniskirt.miniApplication;


public class miniXmppConnection {
	private static final int SMACK_PRIORITY_MIN = -128;
    private static final int SMACK_PRIORITY_MAX = 128;
    private static final String TAG = "XMPPConnectionAdapter";
    private final XMPPConnection mAdaptee;
//    private IChatManager mChatManager;
    private final String mLogin;
    private final String mPassword;
    private String mResource;
    private String mErrorMsg;
//    private RosterAdapter mRoster;
    private int mPreviousPriority;
    private int mPreviousMode;
    private String mPreviousStatus;
//    private PrivacyListManagerAdapter mPrivacyListManager;
    private ChatStateManager mChatStateManager;
    private final miniService mService;
    private miniApplication mApplication;
//    private BeemAvatarManager mAvatarManager;
//    private PepSubManager mPepManager;
    private SharedPreferences mPref;
//    private final RemoteCallbackList<IBeemConnectionListener> mRemoteConnListeners =
//	new RemoteCallbackList<IBeemConnectionListener>();
//    private final SubscribePacketListener mSubscribePacketListener = new SubscribePacketListener();

//    private final ConnexionListenerAdapter mConListener = new ConnexionListenerAdapter();
//
//    private UserInfo mUserInfo;
//    private final UserInfoManager mUserInfoManager = new UserInfoManager();
    /**
     * Constructor.
     * @param config Configuration to use in order to connect
     * @param jid the jid of the user
     * @param login login to use on connect
     * @param password password to use on connect
     * @param service the background service associated with the connection.
     */
    public miniXmppConnection(final ConnectionConfiguration config, final String jid,
	    final String login, final String password, final miniService service) {
	this(new XMPPConnection(config), jid, login, password, service);
    }

    /**
     * Constructor.
     * @param serviceName name of the service to connect to
     * @param jid the jid of the user
     * @param login login to use on connect
     * @param password password to use on connect
     * @param service the background service associated with the connection.
     */
    public miniXmppConnection(final String serviceName, final String jid,
	    final String login, final String password, final miniService service) {
	this(new XMPPConnection(serviceName), jid, login, password, service);
    }

    /**
     * Constructor.
     * @param con The connection to adapt
     * @param jid the jid of the user
     * @param login The login to use
     * @param password The password to use
     * @param service the background service associated with the connection.
     */
    public miniXmppConnection(final XMPPConnection con, final String jid,
	    final String login, final String password, final miniService service) {
	mAdaptee = con;
	PrivacyListManager.getInstanceFor(mAdaptee);
	mLogin = login;
	mPassword = password;
	mService = service;
	Context ctx = mService.getApplicationContext();
//	mUserInfo = new UserInfo(jid.toLowerCase());
	if (ctx instanceof miniApplication) {
	    mApplication = (miniApplication) ctx;
	}
	mPref = mService.getServicePreference();
	try {
	    mPreviousPriority = Integer.parseInt(mPref.getString("settings_key_priority", "0"));
	} catch (NumberFormatException ex) {
	    mPreviousPriority = 0;
	}
	mResource = mPref.getString("settings_key_resource", "miniskirt");
    }
    /**
     * Get the Smack XmppConnection.
     * @return Smack XmppConnection
     */
    public XMPPConnection getAdaptee() {
	return mAdaptee;
    }
    
    public boolean connect() throws RemoteException {
    	if (mAdaptee.isConnected())
    	    return true;
    	else {
    	    try {
    		mAdaptee.connect();
//    		mAdaptee.addConnectionListener(mConListener);//有必要实现
    		return true;
    	    } catch (XMPPException e) {
    		Log.e(TAG, "Error while connecting", e);
    		try {
    		    //TODO NIKITA DOES SOME SHIT !!! Fix this monstruosity
    		    String str = mService.getResources().getString(
    			mService.getResources().getIdentifier(
    			    e.getXMPPError().getCondition().replace("-", "_"), "string", "com.android.miniskirt"));
    		    mErrorMsg = str;
    		} catch (NullPointerException e2) {
    		    if (!"".equals(e.getMessage()))
    			mErrorMsg = e.getMessage();
    		    else
    			mErrorMsg = e.toString();
    		}
    	    }
    	    return false;
    	}
    }
    
    public boolean login() throws RemoteException {
    	if (mAdaptee.isAuthenticated())
    	    return true;
    	if (!mAdaptee.isConnected())
    	    return false;
    	try {

//    	    this.initFeatures(); // pour declarer les features xmpp qu'on
    	    // supporte

    	    PacketFilter filter = new PacketFilter() {

    		@Override
    		public boolean accept(Packet packet) {
    		    if (packet instanceof Presence) {
    			Presence pres = (Presence) packet;
    			if (pres.getType() == Presence.Type.subscribe)
    			    return true;
    		    }
    		    return false;
    		}
    	    };

//    	    mAdaptee.addPacketListener(mSubscribePacketListener, filter);

    	    mAdaptee.login(mLogin, mPassword, mResource);
//    	    mChatManager = new BeemChatManager(mAdaptee.getChatManager(), mService);
    	    //nikita: I commented this line because of the logs provided in http://www.beem-project.com/issues/321
    	    //Also, since the privacylistmanager isn't finished and used, it will be safer to not initialize it
    	    //mPrivacyListManager = new PrivacyListManagerAdapter(PrivacyListManager.getInstanceFor(mAdaptee));
    	    mService.initJingle(mAdaptee);
//    	    discoverServerFeatures();

//    	    mRoster = new RosterAdapter(mAdaptee.getRoster(), mService, mAvatarManager);
    	    mApplication.setConnected(true);
    	    int mode = mPref.getInt(miniApplication.STATUS_KEY, 0);
    	    String status = mPref.getString(miniApplication.STATUS_TEXT_KEY, "");
    	    changeStatus(mode, status);
    	    return true;
    	} catch (XMPPException e) {
    	    Log.e(TAG, "Error while connecting", e);
//    	    mErrorMsg = mService.getString(R.string.error_login_authentication);
    	    return false;
    	}
        }
    
    public boolean connectSync() throws RemoteException {
    	if (connect())
    	    return login();
    	return false;
    }
    
    public final void connectAsync() throws RemoteException {
    	if (mAdaptee.isConnected() || mAdaptee.isAuthenticated())
    	    return;
    	Thread t = new Thread(new Runnable() {

    	    @Override
    	    public void run() {
    		try {
    		    connectSync();
    		} catch (RemoteException e) {
    		    Log.e(TAG, "Error while connecting asynchronously", e);
    		}
    	    }
    	});
    	t.start();
    }
    
    public void changeStatus(int status, String msg) {
    	changeStatusAndPriority(status, msg, mPreviousPriority);
        }
    public void changeStatusAndPriority(int status, String msg, int priority) {
    	Presence pres = new Presence(Presence.Type.available);
    	String m;
    	if (msg != null)
    	    m = msg;
    	else
    	    m = mPreviousStatus;
    	pres.setStatus(m);
    	mPreviousStatus = m;
//    	Presence.Mode mode = Status.getPresenceModeFromStatus(status);
//    	if (mode != null) {
//    	    pres.setMode(mode);
//    	    mPreviousMode = status;
//    	} else {
//    	    pres.setMode(Status.getPresenceModeFromStatus(mPreviousMode));
//    	}
    	int p = priority;
    	if (priority < SMACK_PRIORITY_MIN)
    	    p = SMACK_PRIORITY_MIN;
    	if (priority > SMACK_PRIORITY_MAX)
    	    p = SMACK_PRIORITY_MAX;
    	mPreviousPriority = p;
    	pres.setPriority(p);
    	mAdaptee.sendPacket(pres);
//    	updateNotification(m);
        }
    /**
     * Update the notification for the Beem status.
     * @param text the text to display.
     */
//    private void updateNotification(String text) {
//	Notification mStatusNotification;
//	mStatusNotification = new Notification(com.beem.project.beem.R.drawable.beem_status_icon, text, System
//	    .currentTimeMillis());
//	mStatusNotification.defaults = Notification.DEFAULT_LIGHTS;
//	mStatusNotification.flags = Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
//
//	mStatusNotification.setLatestEventInfo(mService, "Beem Status", text, PendingIntent.getActivity(mService, 0,
//	    new Intent(mService, ChangeStatus.class), 0));
//	// bypass the preferences for notification
//	mService.getNotificationManager().notify(BeemService.NOTIFICATION_STATUS_ID, mStatusNotification);
//    }
    public boolean disconnect() {
    	if (mAdaptee != null && mAdaptee.isConnected())
    	    mAdaptee.disconnect();
    	return true;
    }
    
    /**
     * Returns true if currently authenticated by successfully calling the login method.
     * @return true when successfully authenticated
     */
    public boolean isAuthentificated() {
	return mAdaptee.isAuthenticated();
    }
}